#pragma once

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <unistd.h>
#include <openssl/sha.h> // 用于sha1加密
#include <openssl/evp.h>
#include <termios.h>  // 用于 termios 结构体和 tcgetattr / tcsetattr
#include <crypt.h>
#include <time.h>
#include <signal.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/stat.h>

#include "./cmd_trie.h"
#include "./tlv.h"
#include "./parse_path.h"
#include "./client_log.h"
#include "./ftp.h"

#define    REQUEST_GET_SALT         1
#define    REQUEST_REGISTER         2
#define    REQUEST_LOGIN            3
#define    REQUEST_DEREGISTER       4
#define    REQUEST_CD               10
#define    REQUEST_PWD              11
#define    REQUEST_LS               12
#define    REQUEST_MKDIR            13
#define    REQUEST_RMDIR            14
#define    REQUEST_REMOVE           15
#define    REQUEST_PUTS             21
#define    REQUEST_FILE_PUTS_RESULT 22
#define    REQUEST_GETS             25
#define    REQUEST_EXIT             88
#define    RESPONSE                 100

#define    RESPONSE_OK                  100
#define    RESPONSE_ERROR_REQUEST       200
#define    RESPONSE_INVALID_REQUEST     201
#define    RESPONSE_USERNAME_NOT_EXIST  210
#define    RESPONSE_USERNAME_IS_EXIST   211
#define    RESPONSE_PASSWORD_WRONG      220
#define    RESOPNSE_INVALID_TOKEN       230
#define    RESPONSE_TOKEN_EXPIRED       231
#define    RESPONSE_FILE_EXIST          300
#define    RESPONSE_FILE_NOT_EXIST      333
#define    TLV_BUFFER_MAX_SIZE          4096

#define    CMD_MAX                      20
#define    ARG_MAX                      100
#define    CMD_LINE_MAX                 1024
#define    MAX_PATH                     1024
#define    MAX_TOKEN                    512
#define    MAX_DIR_NAME                 1024
#define    TOKEN_LIFETIME_SECONDS       1800 // Token 有效时间

#define ARGS_CHECK(argc,expect){if(argc!=expect){printf("argc num is wrong.\n");exit(-1);}}
#define thread_perror(msg){char error_str[256]; strerror_r(errno,error_str,sizeof(error_str)); fprintf(stderr,"%s:%s\n",msg,error_str);}
#define TLV_VALUE_MAX_SIZE (TLV_BUFFER_MAX_SIZE-sizeof(uint32_t)-sizeof(uint32_t))


// 上下文信息，仅在函数上下文传递时用
typedef struct {
    int sockfd;
    char *username;
    char *password;
}user_info_ctx_t;

// 用户登录后维护的信息
typedef struct{
    int sockfd;
    char ip[64];
    char port[16];
    char sha1[41];
    char username[100];
    char token[MAX_TOKEN];
    timer_t token_timer;
    int flag;
    int filesize;
}client_session;

typedef struct{
    char ip[64];
    char port[16];
    char token[MAX_TOKEN];
    char sha1[48];
    char path[MAX_PATH];
    char filename[256];
    int begin; // 文件偏移量的开始
    int size; // 文件块大小
}thread_args_t;

typedef void(*request_callback_ptr_t)(uint32_t,uint32_t,const uint8_t*,void*);

int connect_to_server(char *ip,char *port_str);

int is_logged_in();

void init_func(trie_t *cmd_dict); 

int tlv_send(int sockfd,uint32_t type,uint32_t length,const uint8_t *value);

int tlv_recv(int sockfd,uint32_t *type,uint32_t *length,uint8_t *value);

int tlv_request(int sockfd,uint32_t type,uint32_t length,const uint8_t *value,request_callback_ptr_t callback,void *arg);
